﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;

namespace SqlProcessViewer
{
	public class DatabaseReader : IEnumerable<DataRecordWrapper>, INotifyPropertyChanged
	{
		#region Constants

		private static string CONNECTIONSTRING_DEFAULT = "DbConnection";

		#endregion

		#region Events

		public event PropertyChangedEventHandler PropertyChanged;

		#endregion

		#region Variables

		private IEnumerable<DataRecordWrapper> _results;

		private DateTime _lastRefresh;
		private TimeSpan _runTime;

		#endregion

		#region Constructors

		static DatabaseReader()
		{
			ConnectionString = ConfigurationManager.ConnectionStrings[CONNECTIONSTRING_DEFAULT].ConnectionString;
		}

		public DatabaseReader(CommandType commandType, string commandText)
		{
			CommandType = commandType;
			CommandText = commandText;
			_results = null;

			Refresh();
		}

		#endregion

		#region Properties

		public static string ConnectionString { get; set; }

		public CommandType CommandType { get; set; }

		public string CommandText { get; set; }

		public DateTime LastRefresh
		{
			get
			{
				return _lastRefresh;
			}
			private set
			{
				if (_lastRefresh != value)
				{
					_lastRefresh = value;
					PropertyHasChanged("LastRefresh");
				}
			}
		}

		public TimeSpan RunTime
		{
			get
			{
				return _runTime;
			}
			private set
			{
				if (_runTime != value)
				{
					_runTime = value;
					PropertyHasChanged("RunTime");
				}
			}
		}

		#endregion

		#region Methods

		public void Refresh()
		{
			var timer = new Stopwatch();
			timer.Start();
			using (var cn = new SqlConnection(ConnectionString))
			{
				cn.Open();
				using (var cm = cn.CreateCommand())
				{
					cm.CommandType = CommandType;
					cm.CommandText = CommandText;

					_results = cm.ExecuteReader()
						.Cast<IDataRecord>()
						.ToArray()
						.Select(x => new DataRecordWrapper(x));
					//.Cast<dynamic>(); //TODO: Implement IEnumerable<dymamic>??
				}
			}
			timer.Stop();
			RunTime = timer.Elapsed;
			LastRefresh = DateTime.Now;
		}

		public IEnumerator<DataRecordWrapper> GetEnumerator()
		{
			return _results.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		private void PropertyHasChanged(string propertyName)
		{
			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}

		#endregion
	}
}